#ifndef PORTABLE_BYTECODE_JUMP_TABLE_H_
#define PORTABLE_BYTECODE_JUMP_TABLE_H_

#include "src/pbc/portable-logging.h"
namespace portable {

// A jump table for a set of targets in a bytecode array. When an entry in the
// table is bound, it represents a known position in the bytecode array. If no
// entries match, the switch falls through.
class BytecodeJumpTable final {
 public:
  // Constructs a new BytecodeJumpTable starting at |constant_pool_index|, with
  // the given |size|, where the case values of the table start at
  // |case_value_base|.
  BytecodeJumpTable(size_t constant_pool_index, int size, int case_value_base)
      : constant_pool_index_(constant_pool_index),
        switch_bytecode_offset_(kInvalidOffset),
        size_(size),
        case_value_base_(case_value_base) {}

  size_t constant_pool_index() const { return constant_pool_index_; }
  size_t switch_bytecode_offset() const { return switch_bytecode_offset_; }
  int case_value_base() const { return case_value_base_; }
  int size() const { return size_; }
  // #ifdef DEBUG
  //   bool is_bound(int case_value) const {
  //     P_CHECK_GE(case_value, case_value_base_);
  //     P_CHECK_LT(case_value, case_value_base_ + size());
  //     return bound_.Contains(case_value - case_value_base_);
  //   }
  // #endif

  size_t ConstantPoolEntryFor(int case_value) {
    P_DCHECK_GE(case_value, case_value_base_);
    return constant_pool_index_ + case_value - case_value_base_;
  }

 private:
  static const size_t kInvalidIndex = static_cast<size_t>(-1);
  static const size_t kInvalidOffset = static_cast<size_t>(-1);

  void mark_bound(int case_value) {
    // #ifdef DEBUG
    //     P_CHECK_GE(case_value, case_value_base_);
    //     P_CHECK_LT(case_value, case_value_base_ + size());
    //     bound_.Add(case_value - case_value_base_);
    // #endif
  }

  void set_switch_bytecode_offset(size_t offset) {
    P_DCHECK_EQ(switch_bytecode_offset_, kInvalidOffset);
    switch_bytecode_offset_ = offset;
  }

  // #ifdef DEBUG
  //   // This bit vector is only used for DCHECKS, so only store the field in
  //   debug
  //   // builds.
  //   BitVector bound_;
  // #endif
  size_t constant_pool_index_;
  size_t switch_bytecode_offset_;
  int size_;
  int case_value_base_;

  friend class BytecodeArrayWriter;
};

}  // namespace portable

#endif  // PORTABLE_BYTECODE_JUMP_TABLE_H_
